package com.jadows.tdog.message.handler.impl;

import cn.hutool.core.collection.CollUtil;
import com.jadows.tdog.constants.CacheConstants;
import com.jadows.tdog.constants.GlobalActions;
import com.jadows.tdog.domain.ChatMessage;
import com.jadows.tdog.domain.ChatRoom;
import com.jadows.tdog.exception.ServiceException;
import com.jadows.tdog.message.WsReqWrapper;
import com.jadows.tdog.message.details.RoomTextMessage;
import com.jadows.tdog.message.handler.IMqMessageHandler;
import com.jadows.tdog.repository.ChatMessageRepository;
import com.jadows.tdog.repository.ChatRoomRepository;
import com.jadows.tdog.server.codec.JsonWebSocketFrame;
import com.jadows.tdog.service.ChatRoomService;
import com.jadows.tdog.state.SimpleWSSessionUtil;
import io.netty.channel.Channel;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RTopic;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import java.util.Set;

/**
 * @author taojiacheng
 */
@Service
@Slf4j
public class RoomTextMessageHandler implements IMqMessageHandler<WsReqWrapper<RoomTextMessage>> {

    final RTopic rTopic;
    final RedissonClient redissonClient;
    final ChatRoomService chatRoomService;
    final ChatMessageRepository chatMessageRepository;
    final ChatRoomRepository chatRoomRepository;

    public RoomTextMessageHandler(RedissonClient redissonClient, ChatRoomService chatRoomService, ChatMessageRepository chatMessageRepository, ChatRoomRepository chatRoomRepository) {
        this.redissonClient = redissonClient;
        this.chatRoomService = chatRoomService;
        rTopic = redissonClient.getTopic(CacheConstants.ROOM_TEXT_MSG_TOPIC);
        rTopic.addListener(WsReqWrapper.class, (channel, msg) -> {
            log.info("RoomTextMessageHandler: {}", msg);
            @SuppressWarnings("unchecked") WsReqWrapper<RoomTextMessage> reqWrapper = (WsReqWrapper<RoomTextMessage>) msg;
            this.arrived(reqWrapper);
        });
        this.chatMessageRepository = chatMessageRepository;
        this.chatRoomRepository = chatRoomRepository;
    }

    public void handleRoomTextMessage(WsReqWrapper<RoomTextMessage> reqWrapper) {
        RoomTextMessage data = reqWrapper.getData();
        Long roomId = data.getRoomId();
        if (roomId == null) {
            throw new IllegalArgumentException("roomId 不能为空");
        }
        // 获取群组
        ChatRoom chatRoom = chatRoomRepository.findById(roomId).orElseThrow(() -> new ServiceException("房间不存在"));
        // 判断是否是群成员
        String fromUid = data.getFromUid();
        boolean contains = chatRoom.getMemberIds().contains(fromUid);
        if (!contains) {
            throw new ServiceException("用户不在房间内");
        }
        // 存储消息
        this.persistenceMessage(data);
        this.publish(reqWrapper);
    }

    /**
     * 持久化消息
     *
     * @param data 消息
     */
    public void persistenceMessage(RoomTextMessage data) {
        ChatMessage chatMessage = new ChatMessage();
        BeanUtils.copyProperties(data, chatMessage);
        chatMessage.setAction(GlobalActions.ROOM_TEXT_MSG);
        chatMessageRepository.save(chatMessage);
    }

    /**
     * 广播消息
     *
     * @param message 消息
     * @return Long
     */
    @Override
    public Long publish(WsReqWrapper<RoomTextMessage> message) {
        return rTopic.publish(message);
    }

    @Override
    public void arrived(WsReqWrapper<RoomTextMessage> reqWrapper) {
        RoomTextMessage textMessage = reqWrapper.getData();
        Long roomId = textMessage.getRoomId();
        Set<String> roomMembers = chatRoomService.getRoomMembers(roomId);
        for (String uid : roomMembers) {
            Set<Channel> channels = SimpleWSSessionUtil.getChannelByUid(uid);
            if (CollUtil.isEmpty(channels)) {
                continue;
            }
            channels.forEach(channel ->
                    channel.writeAndFlush(new JsonWebSocketFrame(reqWrapper)));
        }
    }


}
